#ifndef __IOmanager_H__
#define __IOmanager_H__

#include "scheduler.h"
#include "timer.h"

namespace framework
{

//基于epoll的IO协程调度器
class IOManager : public Scheduler , public TimerManager
{
public:
    using ptr = std::shared_ptr<IOManager>;
    using RWMutexType = RWMutex;

    enum Event
    {
        NONE    = 0x0,
        READ    = 0x1, // 读事件(EPOLLIN)
        WRITE   = 0x4  // 写事件(EPOLLOUT)
    };

    //in 线程池默认线程数量
    //in 是否使用当前调用线程(是否将调用线程包含进去)
    //in 协程调度器名称
    IOManager(size_t threads = 1, bool use_caller = true, const std::string& name = "");
    ~IOManager();

    //添加事件
    //in socket句柄
    //in 事件类型
    //in 事件回调函数
    //return 成功返回0，失败返回-1
    int addEvent(int fd, Event event, std::function<void()> cb = nullptr);

    //删除事件（不会触发事件）
    //in socket句柄
    //in 事件类型
    bool delEvent(int fd, Event event);

    //取消事件（如果事件存在则触发事件）
    //in socket句柄
    //in 事件类型
    bool cancelEvent(int fd, Event event);

    //取消所有事件
    //in socket句柄
    bool cancelAll(int fd);

    //返回当前的IOManager
    static IOManager* GetThis();

protected:
    //通知协程调度器有任务了
    void tickle() override;
    
    //返回是否可以停止
    bool stopping() override;

    //协程无任务时可调度执行idle协程
    void idle() override;

    //当有新的定时器插入到定时器的首部，执行该函数
    void onTimerInsertedAtFront() override;

    //重置socket句柄上下文容器的大小
    void contextResize(size_t size);

    //判断是否可以停止
    //in 最近要触发的定时器事件间隔
    bool stopping(uint64_t& timeout);

private:
    //socket事件上下文类
    struct FDContext
    {
        using MutexType = Mutex;

        //事件上下文类
        struct EventContext
        {
            Scheduler* scheduler = nullptr; //事件执行的调度器（事件在那个调度器上执行）
            Fiber::ptr fiber;               //事件协程
            std::function<void()> cb;       //事件回调函数
        };

        //获取事件上下文
        //in 事件类型
        EventContext& getContex(Event event);


        //重置事件上下文
        //[in, out]待重置的上下文类
        void resetContext(EventContext& ctx);

        //触发事件
        //in 事件类型
        void triggerEvent(Event event);

        EventContext read;            //读事件上下文
        EventContext write;           //写事件上下文
        int         fd = 0;           //事件关联的句柄
        Event       events = NONE;    //当前事件
        MutexType   mutex;            //事件锁
    };


    int           m_epfd = 0;      //epoll 红黑树                     
    int           m_tickleFds[2];  //pipe 文件句柄，[0]表示管道的读端,[1] 表示管道的写端。                     
    RWMutexType   m_mutex;         //IOManager的读写锁                       
    std::atomic<size_t>      m_pendingEventCount = {0};   //当前等待执行的事件数量
    std::vector<FDContext*>  m_fdContexts;                  //socket事件上下文的容器
};









}


#endif
